package com.vtron.web.api.service.impl;

import com.vtron.core.HttpCode;
import com.vtron.utils.string.StringUtils;
import com.vtron.web.api.service.ITokenService;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.http.HttpServletRequest;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;
import java.util.Objects;
import java.util.function.Function;

/**
 * @date : 2022/4/15 16:51
 * @author: 忻龙彪
 */
@Service
public class TokenServiceImpl implements ITokenService {

    /** 默认令牌有效期（默认30分钟）*/
    @Value("${token.expireTime:30}")
    private int expireTime;
    /** 令牌私钥 */
    //@Value("${token.priKey}")
    private PrivateKey priKey;
    /** 令牌公钥 */
    // @Value("${token.pubKey}")
    private PublicKey pubKey;
    @Autowired
    protected HttpServletRequest request;

    public TokenServiceImpl() throws  Exception{
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        if (priKey == null && pubKey == null) {
            //KeyPair kp = RsaProvider.generateKeyPair();
            KeyPair kp =kpg.generateKeyPair();
            pubKey = kp.getPublic();
            priKey = kp.getPrivate();
        }
    }

    @Override
    public <T> T getAuthentication(Class<T> clazz) {
        String token = request.getHeader("Authorization");
        Objects.requireNonNull(token,"The token of Authorization cannot be null!");
        String json = parseToken(token).getSubject();
        return JSON.parseObject(json,clazz);
    }

    @Override
    public <T> T getAuthentication(Class<T> clazz, Function<String, T> defaultObj) {
        String token = request.getHeader("Authorization");
        if(StringUtils.isEmpty(token)){
            return defaultObj.apply(token);
        }
        String json = parseToken(token).getSubject();
        return JSON.parseObject(json,clazz);
    }

    @Override
    public String get(String uid, long exp) {
        long endTime = System.currentTimeMillis() + 1000 * 60 * exp;
        return Jwts.builder().setSubject(uid).setExpiration(new Date(endTime))
                .signWith(SignatureAlgorithm.RS512, priKey).compact();
    }

    @Override
    public String get(String uid) {
        return get(uid,expireTime);
    }

    @Override
    public HttpCode check(String token) {

        try {
            if(StringUtils.isEmpty(token)){
                return HttpCode.TOKEN_UNDEFINED;
            }
            parseToken(token).getSubject();
            return HttpCode.SUCCESS;
        } catch (ExpiredJwtException e) {
            // 在解析JWT字符串时，如果‘过期时间字段’已经早于当前时间，将会抛出ExpiredJwtException异常，说明本次请求已经失效
            return HttpCode.TOKEN_TIMEOUT;
        } catch (Exception e) {
            return HttpCode.TOKEN_FAIL;
        }
    }
    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private Claims parseToken(String token)
    {
        return Jwts.parser()
                .setSigningKey(pubKey)
                .parseClaimsJws(token)
                .getBody();
    }
}
